let redis = require('../dao/redis');

let redisConst = require('../const/redisConst');

let clubInfoDao = require('../dao/ClubInfoDao');

const { BusiError, SysError } = require('../exception/exception');

class RoomCacheService {
    constructor(){}

    /**
     * 获取用户房间信息
     * @param {String} uid 
     */
    async getUserRoom(uid) {
        let userRoomInfoCacheKey = redisConst.USER_ROOM_FLAG + ":" + uid;
        let uri = await redis.get(userRoomInfoCacheKey);
        return uri;
    }

    /**
     * 移除用户房间信息
     * @param {String} uid 
     */
    async removeUserRoom(uid){
        let userRoomInfoCacheKey = redisConst.USER_ROOM_FLAG + ":" + uid;
        await redis.del(userRoomInfoCacheKey);
    }

    /**
     * 设置用户房间信息
     * @param {String} uid 
     * @param {Object} roomInfo
     */
    async userEnterRoom(uid, roomInfo){
        let userRoomInfoCacheKey = redisConst.USER_ROOM_FLAG + ":" + uid;
        let res = await redis.setNx(userRoomInfoCacheKey, roomInfo, 60 * 60 * 24); // 缓存最长保留时间为24h)
        if (!res) {
            throw new BusiError(500, "系统异常, 进入房间失败");
        }
    }

    /**
     * 清除用户房间信息
     * @param {String} uid 
     */
    async userLeaveRoom(uid) {
        let userRoomInfoCacheKey = redisConst.USER_ROOM_FLAG + ":" + uid;
        await redis.del(userRoomInfoCacheKey);
    }

    /**
     * 增加缓存中子游戏的在线人数
     * @param gameType 游戏类型
     * @param count  增加的人数
     * @returns {Promise<void>}
     */
    async addGameUserCount(gameType, count){
        if(count === undefined){
            count = 1;
        }
        let gameUserCountCacheKey = redisConst.GAME_USER_COUNT;
        let gameUserCount = await redis.get(gameUserCountCacheKey);
        if(gameUserCount === null){
            gameUserCount = {};
        }
        if(typeof gameUserCount === "string"){
            gameUserCount = JSON.parse(gameUserCount);
        }
        if(gameUserCount[gameType] === undefined){
            gameUserCount[gameType] = 0;
        }
        console.logw(gameType + "子游戏在线人数：", gameUserCount[gameType])
        let beginCount = gameUserCount[gameType];
        if(count < 0 && beginCount <= 0){
            return;
        }
        gameUserCount[gameType] = beginCount +count;
        await redis.set(gameUserCountCacheKey, gameUserCount );
    }

    async setGameUserCount(gameType, count){
        if(count === undefined){
            count = 0;
        }
        let gameUserCountCacheKey = redisConst.GAME_USER_COUNT;
        let gameUserCount = await redis.get(gameUserCountCacheKey);
        if(gameUserCount === null){
            gameUserCount = {};
        }
        if(typeof gameUserCount === "string"){
            gameUserCount = JSON.parse(gameUserCount);
        }
        if(gameUserCount[gameType] === undefined){
            gameUserCount[gameType] = 0;
        }

        gameUserCount[gameType] = count;
        console.logw(gameType + "子游戏在线人数：", gameUserCount[gameType])
        await redis.set(gameUserCountCacheKey, gameUserCount );
    }

    /**
     * 增加缓存中子游戏的在线人数
     * @param gameType 游戏类型
     * @param count  增加的人数
     * @returns {Promise<void>}
     */
    async getGameUserCount(){

        let gameUserCountCacheKey = redisConst.GAME_USER_COUNT;
        let gameUserCount = await redis.get(gameUserCountCacheKey);
        if(!gameUserCount){
            gameUserCount = {};
        }
        return gameUserCount;

    }




    /**
     * 房间是否存活
     * @param {String} roomID 
     */
    async isRoomAlive(roomID){
        let roomTickerCacheKey = redisConst.GAME_ROOM_TICKER_FLAG + ":" + roomID;
        let rti = await redis.get(roomTickerCacheKey);
        if(rti){
            return true;
        }

        return false;
    }

    /**
     * 创建房间设置房间存活标识
     * @param {String} roomID 
     */
    async setRoomAliveNx(roomID){
        let roomTickerCacheKey = redisConst.GAME_ROOM_TICKER_FLAG + ":" + roomID;
        let res = await redis.setNx(roomTickerCacheKey, '1', 60 * 5); // 房间有效时间为5分钟
        if (!res) {
            return false;
        }

        return true;
    }

     /**
     * 设置房间存活标识
     * @param {String} roomID 
     */
    async setRoomAliveEx(roomID){
        let roomTickerCacheKey = redisConst.GAME_ROOM_TICKER_FLAG + ":" + roomID;
        let res = await redis.setXx(roomTickerCacheKey, '1', 60 * 5); // 房间有效时间为5分钟
        if (!res) {
            return false;
        }

        return true;
    }

     /**
     * 移除房间存活标识
     * @param {String} roomID 
     */
    async removeRoomAliveFlag(roomID){
        let roomTickerCacheKey = redisConst.GAME_ROOM_TICKER_FLAG + ":" + roomID;
        let rti = await redis.del(roomTickerCacheKey);
        if(rti){
            return true;
        }

        return false;
    }

    /**
     * 移除俱乐部房间
     * @param {String} clubID 
     * @param {String} roomID 
     */
    async removeClubRoom(clubID, roomID){
        let gameClubRoomCacheKey = redisConst.GAME_CLUB_ROOM_FLAG + ":" + clubID;
        await redis.hdel(gameClubRoomCacheKey, roomID);
    }

    /**
     * 移除俱乐部房间
     * @param {String} clubID
     * @param {String} roomID
     */
    async removeUnionRoom(unionID, roomID){
        let gameUnionRoomCacheKey = redisConst.GAME_UNION_ROOM_FLAG + ":" + unionID;
        await redis.hdel(gameUnionRoomCacheKey, roomID);
    }

    /**
     * 添加房间信息到俱乐部
     * @param {String} clubID
     * @param {String} roomID
     * @param {Object} roomInfo
     */
    async setClubRoom(clubID, roomID, roomInfo){
        let gameClubRoomCacheKey = redisConst.GAME_CLUB_ROOM_FLAG + ":" + clubID;
        let res = await redis.hset(gameClubRoomCacheKey, roomID, roomInfo);
        var   tick=new Date().getTime();
        await  redis.setHashItem(redisConst.gamingMap,roomID,tick)

        return res;
    }

    //add
    /**
     * 添加房间信息到联盟
     * @param {String} clubID
     * @param {String} roomID
     * @param {Object} roomInfo
     */
    async setUnionRoom(unionID, roomID, roomInfo){
        let gameUnionRoomCacheKey = redisConst.GAME_UNION_ROOM_FLAG + ":" + unionID;
        let res = await redis.hset(gameUnionRoomCacheKey, roomID, roomInfo);
        var   tick=new Date().getTime();
        await  redis.setHashItem(redisConst.gamingMap,roomID,tick)
        return res;
    }

    //获取俱乐部信息
    async GetClubCntInfo(clubId,obj){
        let cacheKey = redisConst.GAME_CLUB_ROOM_FLAG + ":" + clubId;
        let roomCnt = 0;
        let m = await redis.hgetall(cacheKey);
        if(m){
            let keys = Object.keys(m);
            for(let i = 0; i < keys.length; i++){
                let k = keys[i];
                let tCacheKey = redisConst.GAME_ROOM_TICKER_FLAG + ":" + k;
                let res = await redis.get(tCacheKey);
                if(res){
                    roomCnt++;
                }
            }
        }

        obj.roomCnt = roomCnt;

        let cnt = 0;
        let memberCntCacheKey = redisConst.GAME_CLUB_MEMBER_CNT + ":" + clubId;
        let rs = await redis.get(memberCntCacheKey);
        if(rs){
            cnt = parseInt(rs);
        }else{
            let rescnt = await clubInfoDao.getClubMembersCntByID(clubId);
            cnt = rescnt["count(1)"];
            await redis.set(memberCntCacheKey, cnt, 300);
        }

        obj.memberCnt = cnt;
    }

    /**
     * 查询俱乐部房间信息
     * @param {String} clubID 
     */
    async queryClubRoom(clubID){
        let gameClubRoomCacheKey = redisConst.GAME_CLUB_ROOM_FLAG + ":" + clubID;
        let res = await redis.hgetall(gameClubRoomCacheKey);

        let arr = [];
        if(res){
            let keys = Object.keys(res);
            for(let i = 0; i < keys.length; i++){
                let key = keys[i];
                let val = res[key];
                let res2 = await this.isRoomAlive(val.roomID);
                if(res2){

                    let userInfos = await this.getRoomUsersMap(val.gt, val.roomID);
                    val.users = userInfos;
                    val.playInfo = {
                        gc: 0
                    };

                    let playInfo = await this.getRoomGameFlag(res2.roomID, res2.gt, res2.ts);
                    if(playInfo){
                        val.playInfo = playInfo;
                    }

                    arr.push(val);
                }else{
                    this.removeClubRoom(clubID, key);
                    this.removeRoom(key);
                }
           }
        }
        
        return arr;
    }

    /**
     * 查询联盟房间信息
     * @param {String} unionID
     */
    async queryUnionRoom(unionID){
        let gameClubRoomCacheKey = redisConst.GAME_UNION_ROOM_FLAG + ":" + unionID;
        let res = await redis.hgetall(gameClubRoomCacheKey);

        let arr = [];
        if(res){
            let keys = Object.keys(res);
            for(let i = 0; i < keys.length; i++){
                let key = keys[i];
                let val = res[key];
                let res2 = await this.isRoomAlive(val.roomID);
                if(res2){

                    let userInfos = await this.getRoomUsersMap(val.gt, val.roomID);
                    val.users = userInfos;
                    val.playInfo = {
                        gc: 0
                    };

                    let playInfo = await this.getRoomGameFlag(res2.roomID, res2.gt, res2.ts);
                    if(playInfo){
                        val.playInfo = playInfo;
                    }

                    arr.push(val);
                }else{
                    this.removeUnionRoom(unionID, key);
                    this.removeRoom(key);
                }
            }
        }

        return arr;
    }


    /**
     * 设置房卡返回标识
     * @param {String} roomID 
     * @param {String} gt 
     * @param {Number} ts 
     * @param {String} owner 
     * @returns {Promise<{Boolean}>}
     */
    async setCardsReturnFlag(roomID, gt, ts, owner) {
        let gameRoomReturnCardsFlagKey = redisConst.GAME_ROOM_RETURN_CARDS_FLAG + ":" + roomID
            + ":" + gt + ":" + ts + ":" + owner;

        let cache = await redis.set(gameRoomReturnCardsFlagKey, "1", 60 * 5);
        if (!cache) {
            console.logw("设置返回房卡标识失败:", gameRoomReturnCardsFlagKey);
            return false;
        }

        return true;
    }

    /**
     * 是否已经返回过房卡 
     * @param {String} roomID 
     * @param {String} gt 
     * @param {Number} ts 
     * @param {String} owner 
     * @returns {Promise<{Boolean}>}
     */
    async isCardsReturn(roomID, gt, ts, owner) {
        let gameRoomReturnCardsFlagKey = redisConst.GAME_ROOM_RETURN_CARDS_FLAG + ":" + roomID
            + ":" + gt + ":" + ts + ":" + owner;

        let cache = await redis.get(gameRoomReturnCardsFlagKey);
        if (cache) {
            return true;
        }

        return false;
    }

    /**
     * 设置房间信息
     * @param {String} roomID 
     * @param {Object} roomInfo 
     */

    async updateGamingTick(roomID){
        var   tick=new Date().getTime();
        await  redis.setHashItem(redisConst.gamingMap,roomID,tick)
    }
    async setRoom(roomID, roomInfo){
        let gameRoomInfoCacheKey = redisConst.GAME_ROOM_FLAG + ":" + roomID;
        let res2 = await redis.set(gameRoomInfoCacheKey, roomInfo, 60 * 60 * 24); // 缓存最长保留时间为24h
        var  key=redisConst.GAME_ROOM_RECREATE+":"+roomID;
        await redis.set(key, roomInfo, 60 * 60 * 24); // 备份创建房间时候的参数信息，用于游戏牌局结束的时候，再重复创建缓存最长保留时间为1小时
        var   tick=new Date().getTime();
        await  redis.setHashItem(redisConst.gamingMap,roomID,tick)
        return res2;
    }

    async getRecreateRoom(roomID){
        let gameRoomInfoCacheKey = redisConst.GAME_ROOM_RECREATE + ":" + roomID;
        let res2 = await redis.get(gameRoomInfoCacheKey); // 缓存最长保留时间为24h
        return res2;
    }

    async getRecreateLockInfo(roomID){
        let gameRoomInfoCacheKey = redisConst.game_recreate_lock + ":" + roomID;
        let res2 = await redis.get(gameRoomInfoCacheKey); // 缓存最长保留时间为24h
        return res2;
    }

    async delRecreateLockInfo(roomID){
        let gameRoomInfoCacheKey = redisConst.game_recreate_lock + ":" + roomID;
        let res2 = await redis.del(gameRoomInfoCacheKey);
        return res2;
    }
    async setRecreateLockInfo(roomID,roomInfo){
        let gameRoomInfoCacheKey = redisConst.game_recreate_lock + ":" + roomID;
        let res2 = await redis.set(gameRoomInfoCacheKey,roomInfo,60 * 60*24); // 缓存最长保留时间为24h
        return res2;
    }

    /**
     * 获取房间信息
     * @param {String} roomID 
     */
    async getRoom(roomID){
        let gameRoomInfoCacheKey = redisConst.GAME_ROOM_FLAG + ":" + roomID;
        let res2 = await redis.get(gameRoomInfoCacheKey); // 缓存最长保留时间为24h

        return res2;
    }

    /**
     * 移除房间信息
     * @param {String} roomID 
     */
    async removeRoom(roomID){
        let gameRoomInfoCacheKey = redisConst.GAME_ROOM_FLAG + ":" + roomID;
        let res2 = await redis.del(gameRoomInfoCacheKey); // 缓存最长保留时间为24h
        //await redis.delHashItem(redisConst.gamingMap,roomID);
        return res2;
    }

      /**
     * 设置房间用户列表信息
     * @param {String} uid 
     * @param {String} gt 
     * @param {String} roomID 
     * @param {Object} userInfo
     */
    async setRoomUsersMap(uid, gt, roomID, userInfo){
        try{
            let roomUsersMapKey = redisConst.GAME_ROOM_USERS_MAP + ":" + gt + ":" + roomID;
            await redis.hset(roomUsersMapKey, uid, userInfo);
        }catch(e){
            console.log("set room users map err:", e);
        }
    }

     /**
     * 获取房间用户列表
     * @param {String} gt 
     * @param {String} roomID 
     */
    async getRoomUsersMap(gt, roomID){
        let res = [];
        try{
            let roomUsersMapKey = redisConst.GAME_ROOM_USERS_MAP + ":" + gt + ":" + roomID;
            res = await redis.hvals(roomUsersMapKey);
        }catch(e){
            console.logw("set room users map err:", e);
        }

        return res;
    }

    /**
     * 移除房间用户
     * @param {String} uid 
     * @param {String} gt 
     * @param {String} roomID 
     */
    async removeRoomUserFromMap(uid, gt, roomID){
        try{
            let roomUsersMapKey = redisConst.GAME_ROOM_USERS_MAP + ":" + gt + ":" + roomID;
            await redis.hdel(roomUsersMapKey, uid);
        }catch(e){
            console.logw("del room users map err:", e);
        }
    }

    /**
     * 清除房间用户列表
     * @param {String} gt 
     * @param {String} roomID 
     */
    async clearRoomUsersMap(gt, roomID){
        try{
            let roomUsersMapKey = redisConst.GAME_ROOM_USERS_MAP + ":" + gt + ":" + roomID;
            await redis.del(roomUsersMapKey);
        }catch(e){
            console.log("del room users map err:", e);
        }
    }

    /**
     * 校验房间是否存在
     * @param {String} roomID 
     */
    async checkRoom(roomID){
        let roomTickerCacheKey = redisConst.GAME_ROOM_TICKER_FLAG + ":" + roomID;
        let res = await redis.setXx(roomTickerCacheKey, '1', 60 * 5);
        if (!res) {
            throw new BusiError(500, "该房间不存在或者已经被销毁");
        }
    }

    /**
    * 设置房间游戏标识, 有此标识标识已经进行过游戏, 不必返回房卡
    * @param {String} roomID 
    * @param {String} gt 
    * @param {Number} ts 
    * @param {Number} gc 
    */
    async setRoomGameFlag(roomID, gt, ts, gc) {
        let gamePlayFlagKey = redisConst.GAME_ROOM_PLAY_FLAG + ":" + roomID + ":" + gt + ":" + ts;
        let res = await redis.set(gamePlayFlagKey, {rid: roomID, gt: gt, ts: ts, gc: gc}, 60 * 60 * 24);
        if (!res) {
            console.logw("set fk room game play flag err");
        }
    }

    /**
    * 获取房间游戏标识, 有此标识标识已经进行过游戏, 不必返回房卡
    * @param {String} roomID 
    * @param {String} gt 
    * @param {Number} ts 
    */
    async getRoomGameFlag(roomID, gt, ts){
        let gamePlayFlagKey = redisConst.GAME_ROOM_PLAY_FLAG + ":" + roomID + ":" + gt + ":" + ts;
        let playRes = await redis.get(gamePlayFlagKey);
        return playRes;
    }
}

let roomCacheService = new RoomCacheService();
module.exports = roomCacheService;